package cn.kinoko.controller.manga;

import cn.kinoko.common.aspect.annotation.*;
import cn.kinoko.common.base.model.BaseController;
import cn.kinoko.common.base.model.BaseQuery;
import cn.kinoko.common.base.model.Result;
import cn.kinoko.common.base.validate.ValidGroup;
import cn.kinoko.common.constant.CacheKeyConstant;
import cn.kinoko.model.cnTeam.vo.MemberVO;
import cn.kinoko.model.manga.entity.Manga;
import cn.kinoko.model.manga.query.MangaQuery;
import cn.kinoko.model.manga.req.AppendMemberReq;
import cn.kinoko.model.manga.req.MangaMemberPositionReq;
import cn.kinoko.model.manga.req.MangaReq;
import cn.kinoko.model.manga.vo.*;
import cn.kinoko.service.manga.MangaService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author kinoko
 */
@RestController
@RequestMapping("/manga")
public class MangaController extends BaseController {

    @Resource
    private MangaService mangaService;

    @PostMapping("/homePage")
    public Result<Page<MangaVO>> homePage(@RequestBody BaseQuery query) {
        return success(mangaService.homePage(query));
    }

    @PostMapping("/mineMange")
    public Result<Page<MangaVO>> mineMange(@RequestBody MangaQuery query) {
        return success(mangaService.mineMange(query));
    }

    @GetMapping("/heatRanking")
    public Result<List<MangaVO>> top10Manga(@RequestParam Integer cycle) {
        return success(mangaService.top10Manga(cycle));
    }

    @GetMapping("/updateRanking")
    public Result<List<MangaVO>> top10UpdateManga(@RequestParam Integer cycle) {
        return success(mangaService.top10UpdateManga(cycle));
    }

    @PostMapping("/searchManga")
    public Result<Page<MangaSearchVO>> searchManga(@RequestBody MangaQuery query) {
        return success(mangaService.searchManga(query));
    }

    @GetMapping("/plusView")
    public Result<Object> plusView(@RequestParam Long mangaId, HttpServletRequest request) {
        return success(mangaService.plusView(mangaId, request));
    }

    @SlidingWindowLimiter(key = CacheKeyConstant.LIKE_LOCK, params = "#mangaId", currentUser = true, maxRequest = 1)
    @GetMapping("/like")
    public Result<Object> like(@RequestParam Long mangaId, Boolean isLike) {
        return success(mangaService.like(mangaId, isLike));
    }

    @GetMapping("/likeCount")
    public Result<Object> likeCount(@RequestParam Long mangaId) {
        return success(mangaService.likeCount(mangaId));
    }

    @PostMapping(value = "/save")
    public Result<Object> save(@RequestBody @Validated({ValidGroup.Insert.class}) MangaReq req) {
        return toAjax(mangaService.saveManga(req));
    }

    @OwnershipCheck(bizId = "#req.mangaId", bizClass = Manga.class)
    @CacheEvict(key = CacheKeyConstant.MG_DT, params = "#req.mangaId")
    @PostMapping(value = "/update")
    public Result<Object> update(@RequestBody @Validated({ValidGroup.Update.class}) MangaReq req) {
        return toAjax(mangaService.updateManga(req));
    }

    @GetMapping(value = "/checkNameExist")
    public Result<Object> checkNameExist(@RequestParam String name) {
        return success(mangaService.lambdaQuery().eq(Manga::getName, name).exists());
    }

    @OwnershipCheck(bizId = "#mangaId", bizClass = Manga.class)
    @GetMapping("/available")
    public Result<Object> available(@RequestParam Long mangaId, @RequestParam Boolean isAvailable) {
        return toAjax(mangaService.available(mangaId, isAvailable));
    }

    @OwnershipCheck(bizId = "#mangaId", bizClass = Manga.class)
    @GetMapping("/deleted")
    public Result<Object> deleted(@RequestParam Long mangaId) {
        return toAjax(mangaService.deleted(mangaId));
    }

    @GetMapping("/info/{mangaId}")
    @Cacheable(key = CacheKeyConstant.MG_DT, params = "#mangaId")
    public Result<MangaInfoVO> info(@PathVariable Long mangaId) {
        return success(mangaService.info(mangaId));
    }

    @GetMapping("/epList/{mangaId}")
    @Cacheable(key = CacheKeyConstant.MG_EP_LIST, params = "#mangaId")
    public Result<List<MangaEpVO>> epList(@PathVariable Long mangaId) {
        return success(mangaService.epList(mangaId));
    }

    @GetMapping("/nocache/epList/{mangaId}")
    public Result<List<MangaEpVO>> noCacheEpList(@PathVariable Long mangaId) {
        return success(mangaService.epList(mangaId));
    }

    @GetMapping("/mangaMember")
    public Result<List<MemberVO>> mangaMember(@RequestParam Long mangaId) {
        return success(mangaService.mangaMember(mangaId));
    }

    @GetMapping("/mangaMemberByEp")
    public Result<List<MemberVO>> mangaMemberByEpId(@RequestParam Long epId) {
        return success(mangaService.mangaMemberByEpId(epId));
    }

    @GetMapping("/position")
    public Result<Object> position() {
        return success(mangaService.positionList());
    }

    @PostMapping("/changePosition")
    @OwnershipCheck(bizId = "#req.mangaId", bizClass = Manga.class, isShared = true)
    @CacheEvict(key = CacheKeyConstant.MG_MEMBER_LIST, params = "#req.mangaId")
    public Result<Object> changePosition(@RequestBody @Validated MangaMemberPositionReq req) {
        return success(mangaService.changePosition(req));
    }

    @PostMapping("/appendMember")
    @OwnershipCheck(bizId = "#req.mangaId", bizClass = Manga.class, isShared = true)
    @CacheEvict(key = CacheKeyConstant.MG_MEMBER_LIST, params = "#req.mangaId")
    public Result<Object> appendMember(@RequestBody @Validated AppendMemberReq req) {
        return success(mangaService.appendMember(req));
    }

    @GetMapping("/removeMember")
    @OwnershipCheck(bizId = "#req.mangaId", bizClass = Manga.class, isShared = true)
    @CacheEvict(key = CacheKeyConstant.MG_MEMBER_LIST, params = "#mangaId")
    public Result<Object> removeMember(@RequestParam Long mangaId, @RequestParam Long uid) {
        return success(mangaService.removeMember(mangaId, uid));
    }

}
